﻿using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.IO;

using Vestras.StarCraft2.Luna.Parser.Ast;

namespace Vestras.StarCraft2.Luna.Parser {
    public static class ErrorSink {
        static List<Error> lastErrors = new List<Error>();
        static List<Error> errors = new List<Error>();

        public static ReadOnlyCollection<Error> Errors {
            get {
                return new ReadOnlyCollection<Error>(errors);
            }
        }

        public static void AddError(Error error) {
            errors.Add(error);
        }

        public static void Clear() {
            errors.Clear();
        }

        public static void UpdateChangeCollection() {
            lastErrors = errors;
        }

        public static bool HasChanged() {
            bool value = errors.Count != lastErrors.Count;
            lastErrors = errors;
            return value;
        }

        public sealed class Error {
            int startLine;
            int startColumn;
            int endLine;
            int endColumn;
            string fileName;

            public string Description { get; internal set; }
            public Entity Entity { get; internal set; }
            public int StartLine {
                get {
                    return Entity == null ? startLine : Entity.StartLine;
                }
            }

            public int StartColumn {
                get {
                    return Entity == null ? startColumn : Entity.StartColumn;
                }
            }

            public int EndLine {
                get {
                    return Entity == null ? endLine : Entity.EndLine;
                }
            }

            public int EndColumn {
                get {
                    return Entity == null ? endColumn : Entity.EndColumn;
                }
            }

            public string FileName {
                get {
                    return Entity == null ? fileName : Entity.FileName;
                }
            }

            public override string ToString() {
                return string.Format("{0}: Line: {1}, column: {2} -- \"{3}\"", Path.GetFileName(FileName), StartLine + 1, StartColumn + 1, Description);
            }

            private Error() { }
            public static Error Create(string description, Entity entity) {
                if (string.IsNullOrEmpty(description)) {
                    throw new ArgumentNullException("description");
                }

                if (entity == null) {
                    throw new ArgumentNullException("entity");
                }

                Error error = new Error();
                error.Description = description;
                error.Entity = entity;
                return error;
            }

            public static Error Create(string description, int startLine, int startColumn, int endLine, int endColumn, string fileName) {
                if (string.IsNullOrEmpty(description)) {
                    throw new ArgumentNullException("description");
                }

                if (startLine < 0) {
                    throw new ArgumentException("startLine is less than zero.");
                }

                if (startColumn < 0) {
                    throw new ArgumentException("startColumn is less than zero.");
                }

                if (endLine < 0) {
                    throw new ArgumentException("endLine is less than zero.");
                }

                if (endColumn < 0) {
                    throw new ArgumentException("endColumn is less than zero.");
                }

                if (string.IsNullOrEmpty(fileName)) {
                    throw new ArgumentNullException("fileName");
                }

                Error error = new Error();
                error.Description = description;
                error.startLine = startLine;
                error.startColumn = startColumn;
                error.endLine = endLine;
                error.endColumn = endColumn;
                error.fileName = fileName;
                return error;
            }
        }
    }
}
